// 大小端检查
class bs_endian {
  static is_little = function() {
    let l_src_array = new ArrayBuffer(2);
    let l_data_view = new DataView(l_src_array);
     // 第三个参数指定以little endian写入数据
    l_data_view.setInt16(0, 1, true);
    // 此时buf里的内存布局应该是（低地址到高地址） \x01 00
    let l_int16_view = new Int16Array(l_src_array, 0, 1);
    // 如果以little endian读取，它就是1；以big endian读取，则是1*256
    return (l_int16_view[0] === 1);
  }();
};

// 输入流辅助类
class bs_in_stream {
    constructor(_length = 0, _data = null, _offset = 0) {
        this.offset_ = _offset;
        this.length_ = _length;
        this.data_ = _data;  
    }

    // 数据大小端转换
    transfor_endian(_data, _index, _length) {
        if (length % 2 !== 0) {
            return;
        }
        let times = _length / 2;

        let l_transfor_view = new Int8Array(_data, _index, _length);
        for (let index = 0; index < times; ++index) {
            let l_transfor_index = _length - 1 - index;
            let l_tmp_vl = l_transfor_view[index];
            l_transfor_view[index] = l_transfor_view[l_transfor_index];
            l_transfor_view[l_transfor_index] = l_tmp_vl;
        }
    }

    // 读取8位的有符号和无符号整型
    read_u_i_8(_is_signed) { 
        if (this.left() < 1) {
            return null;
        }
        let l_result_view;
        if (_is_signed) {
            l_result_view = new Int8Array(this.data_, this.offset_, 1);
        } else {
            l_result_view = new Uint8Array(this.data_, this.offset_, 1);
        }
        this.shift(1);
        return l_result_view[0];
    }
    // 读取16位的有符号和无符号整型
    read_u_i_16(_is_signed) {
        if (this.left() < 2) {
            return null;
        }
        let l_result_view = null;
        if(bs_endian.is_little || (this.offset_ % 2 !== 0)) {
            let l_transfor_data = this.data_.slice(this.offset_, this.offset_ + 2);
            if (bs_endian.is_little) {
                transfor_endian(l_transfor_data, 0, 2);
            }
            if (_is_signed) {
                l_result_view = new Int16Array(l_transfor_data, 0, 1);
            } else {
                l_result_view = new Uint16Array(l_transfor_data, 0, 1);
            }
        } else {
            if (_is_signed) {
                l_result_view = new Int16Array(this.data_, this.offset_, 1);
            } else {
                l_result_view = new Uint16Array(this.data_, this.offset_, 1);
            }
        }
        this.shift(2);
        return l_result_view[0];
    }
    // 读取32位的有符号和无符号整型
    read_u_i_32(_is_signed) {
        if (this.left() < 4) {
            return null;
        }
        let l_result_view = null;
        if(bs_endian.is_little || (this.offset_ % 4 !== 0)) {
            let l_transfor_data = this.data_.slice(this.offset_, this.offset_ + 4);
            if (bs_endian.is_little) {
                transfor_endian(l_transfor_data, 0, 4);
            }
            if (_is_signed) {
                l_result_view = new Int32Array(l_transfor_data, 0, 1);
            } else {
                l_result_view = new Uint32Array(l_transfor_data, 0, 1);
            }
        } else {
            if (_is_signed) {
                l_result_view = new Int32Array(this.data_, this.offset_, 1);
            } else {
                l_result_view = new Uint32Array(this.data_, this.offset_, 1);
            }
        }
        this.shift(4);
        return l_result_view[0];
    }
    // 读取64位的有符号整型
    read_i_64() {
        if (this.left() < 8) {
            return null;
        }
        let l_value = 0;
        let l_transfor_data = this.data_.slice(this.offset_, this.offset_ + 8);
        if (bs_endian.is_little) {
            transfor_endian(l_transfor_data, 0, 8);
        }
        let l_ui8_view_src = new Uint8Array(l_transfor_data, 0, 8);
        if (l_ui8_view_src[7] >= 128) {
            // 负数
            let l_index = -1;
            for(let i = 0; i < 8; ++i) {
                if(0 == l_ui8_view_src[i]) {
                    l_ui8_view_src[i] = 0xFF;
                } else {
                    l_index = i;
                    l_ui8_view_src[i] = l_ui8_view_src[i] - 1;
                    break;
                }
            }
            for(let i = 0; i < 8; ++i) {
                l_ui8_view_src[i] = 0xFF - l_ui8_view_src[i];
            }
            for(let i = 7; i >= 0; --i) {
                l_value = (l_value * 256) + l_ui8_view_src[i];
            }
            l_value = -l_value;
        } else {
            let l_ui32_view_src = new Uint32Array(l_transfor_data, 0, 2);
            l_value = l_ui32_view_src[0] + l_ui32_view_src[1] * 4294967296;
        }
        this.shift(8);
        return l_value;
    }
    // 读取32位的浮点数
    read_f_32() {
        if (this.left() < 4) {
            return null;
        }
        let l_result_view;
        if (bs_endian.is_little || (this.offset_ % 4 !== 0)) {
            let l_transfor_data = this.data_.slice(this.offset_, this.offset_ + 4);
            if (bs_endian.is_little) {
                transfor_endian(l_transfor_data, 0, 4);
            }
            l_result_view = new Float32Array(l_transfor_data, 0, 1);
        } else {
            l_result_view = new Float32Array(this.data_, this.offset_, 1);
        }
        this.shift(4);
        return l_result_view[0];
    }
    // 读取64位的浮点数
    read_f_64() {
        if (this.left() < 8) {
            return null;
        }
        let l_result_view;
        if (bs_endian.is_little || (this.offset_ % 4 !== 0)) {
            let l_transfor_data = this.data_.slice(this.offset_, this.offset_ + 8);
            if (bs_endian.is_little) {
                transfor_endian(l_transfor_data, 0, 8);
            }
            l_result_view = new Float64Array(l_transfor_data, 0, 1);
        } else {
            l_result_view = new Float64Array(this.data_, this.offset_, 1);
        }
        this.shift(8);
        return l_result_view[0];
    }

    // 指定长度的uint8_view
    uint8_view(_length) {
        if (this.left() < _length) {
            return null;
        }
        let l_result_view = new Uint8Array(this.data_, this.offset_, _length);
        this.shift(_length);
        return l_result_view;
    }

    child_stream(_length) {
        if (this.left() < _length) {
            return null;
        }

        let l_stream = bs_in_stream(this.offset_ + _length, this.data_, this.offset_);
        this.shift(_length);
        return l_stream;
    }

    left() { return this.length_ - this.offset_; }
    shift(_vl) { this.offset_ = this.offset_ + _vl; }
}

// 输出流辅助类
class bs_out_stream {
    constructor(_length = 0, _data = null, _offset = 0) {
        this.offset_ = _offset;
        this.length_ = _length;
        this.data_ = _data;  
    }

    // 写入8位的有符号和无符号整型
    write_u_i_8(_value, _is_signed) { 
        if (this.left() < 1) {
            return false;
        }
        let l_result_view;
        if (_is_signed) {
            l_result_view = new Int8Array(this.data_, this.offset_, 1);
        } else {
            l_result_view = new Uint8Array(this.data_, this.offset_, 1);
        }
        l_result_view[0] = _value;
        this.shift(1);
        return true;
    }
    // 写入16位的有符号和无符号整型
    write_u_i_16(_vlue, _is_signed) {
        if (this.left() < 2) {
            return false;
        }
        let l_result_view = null;
        if((this.offset_ % 2 !== 0)) {
            let l_transfor_data = new ArrayBuffer(2);
            if (_is_signed) {
                l_result_view = new Int16Array(l_transfor_data, 0, 1);
            } else {
                l_result_view = new Uint16Array(l_transfor_data, 0, 1);
            }
            l_result_view[0] = _vlue;
            let l_ui8_view_src = new Uint8Array(l_transfor_data, 0, 2);
            let l_ui8_view_dst = new Uint8Array(this.data_, this.offset_, 2);
            l_ui8_view_dst[0] = l_ui8_view_src[0];
            l_ui8_view_dst[1] = l_ui8_view_src[1];
        } else {
            if (_is_signed) {
                l_result_view = new Int16Array(this.data_, this.offset_, 1);
            } else {
                l_result_view = new Uint16Array(this.data_, this.offset_, 1);
            }
            l_result_view[0] = _vlue;
        }
        if (bs_endian.is_little) {
            transfor_endian(this.data_, this.offset_, 2);
        }
        this.shift(2);
        return true;
    }
    // 写入32位的有符号和无符号整型
    write_u_i_32(_value, _is_signed) {
        if (this.left() < 4) {
            return false;
        }
        let l_result_view = null;
        if(this.offset_ % 4 !== 0) {
            let l_transfor_data = new ArrayBuffer(4);
            if (_is_signed) {
                l_result_view = new Int32Array(l_transfor_data, 0, 1);
            } else {
                l_result_view = new Uint32Array(l_transfor_data, 0, 1);
            }
            l_result_view[0] = _vlue;
            let l_ui8_view_src = new Uint8Array(l_transfor_data, 0, 4);
            let l_ui8_view_dst = new Uint8Array(this.data_, this.offset_, 4);
            l_ui8_view_dst[0] = l_ui8_view_src[0];
            l_ui8_view_dst[1] = l_ui8_view_src[1];
            l_ui8_view_dst[2] = l_ui8_view_src[2];
            l_ui8_view_dst[3] = l_ui8_view_src[3];
        } else {
            if (_is_signed) {
                l_result_view = new Int32Array(this.data_, this.offset_, 1);
            } else {
                l_result_view = new Uint32Array(this.data_, this.offset_, 1);
            }
            l_result_view[0] = _vlue;
        }
        if (bs_endian.is_little) {
            transfor_endian(this.data_, this.offset_, 4);
        }
        this.shift(4);
        return true;
    }
    // 写入64位的有符号整型
    write_i_64(_value) {
        if(0 > _value) {
            // 负数
            _value = - _value;
            if(this.offset_ % 4 !== 0) {
                let l_transfor_data = new ArrayBuffer(8);
                let l_ui32_view_src = new Uint32Array(l_transfor_data, 0, 2);
                l_ui32_view_src[0] = _value & 0xFFFFFFFF;
                l_ui32_view_src[1] = (_value / 4294967296) & 0xFFFFFFFF;
                let l_ui8_view_src = new Uint8Array(l_transfor_data, 0, 8);
                for (let i = 0; i < 8; ++i) {
                    l_ui8_view_src[i] = 0xFF - l_ui8_view_src[i];
                }
                for(let i = 0; i < 8; ++i) {
                    if(0xFF == l_ui8_view_src[i]) {
                        l_ui8_view_src[i] = 0;
                    } else {
                        l_ui8_view_src[i] = l_ui8_view_src[i] + 1;
                        break;
                    }
                }
                let l_ui8_view_dst = new Uint8Array(this.data_, this.offset_, 8);
                for(let i = 0; i < 8; ++i) {
                    l_ui8_view_dst[i] = l_ui8_view_src[i];
                }
            } else {
                let l_ui32_view_src = new Uint32Array(this.data_, this.offset_, 2);
                l_ui32_view_src[0] = _value & 0xFFFFFFFF;
                l_ui32_view_src[1] = (_value / 4294967296) & 0xFFFFFFFF;
                let l_ui8_view_src = new Uint8Array(this.data_, this.offset_, 8);
                for (let i = 0; i < 8; ++i) {
                    l_ui8_view_src[i] = 0xFF - l_ui8_view_src[i];
                }
                for(let i = 0; i < 8; ++i) {
                    if(0xFF == l_ui8_view_src[i]) {
                        l_ui8_view_src[i] = 0;
                    } else {
                        l_ui8_view_src[i] = l_ui8_view_src[i] + 1;
                        break;
                    }
                }
            }
        } else {
            if(this.offset_ % 4 !== 0) {
                let l_transfor_data = new ArrayBuffer(4);
                let l_ui32_view = new Uint32Array(l_transfor_data, 0, 1);
                
                l_ui32_view[0] = _value & 0xFFFFFFFF;
                let l_ui8_view_src = new Uint8Array(l_transfor_data, 0, 4);
                let l_ui8_view_dst = new Uint8Array(this.data_, this.offset_, 8);
                l_ui8_view_dst[0] = l_ui8_view_src[0];
                l_ui8_view_dst[1] = l_ui8_view_src[1];
                l_ui8_view_dst[2] = l_ui8_view_src[2];
                l_ui8_view_dst[3] = l_ui8_view_src[3];
    
                l_ui32_view[0] = (_value / 4294967296) & 0xFFFFFFFF;
                l_ui8_view_dst[4] = l_ui8_view_src[0];
                l_ui8_view_dst[5] = l_ui8_view_src[1];
                l_ui8_view_dst[6] = l_ui8_view_src[2];
                l_ui8_view_dst[7] = l_ui8_view_src[3];
            } else {
                let l_ui32_view_src = new Uint32Array(this.data_, this.offset_, 2);
                l_ui32_view_src[0] = _value & 0xFFFFFFFF;
                l_ui32_view_src[1] = (_value / 4294967296) & 0xFFFFFFFF;
            }
        }
        if (bs_endian.is_little) {
            transfor_endian(this.data_, this.offset_, 8);
        }
        this.shift(8);
        return true;
    }
    // 写入32位浮点数
    write_f_32(_value) {
        if (this.left() < 4) {
            return false;
        }
        if(this.offset_ % 4 !== 0) {
            let l_transfor_data = new ArrayBuffer(4);
            let l_result_view = new Float32Array(l_transfor_data, 0, 1);
            l_result_view[0] = _value;
            let l_ui8_view_src = new Uint8Array(t_byte, 0, 4);
            let l_ui8_view_dst = new Uint8Array(this.data_, this.offset_, 4);
            l_ui8_view_dst[0] = l_ui8_view_src[0];
            l_ui8_view_dst[1] = l_ui8_view_src[1];
            l_ui8_view_dst[2] = l_ui8_view_src[2];
            l_ui8_view_dst[3] = l_ui8_view_src[3];
        } else {
            let l_result_view = new Float32Array(this.data_, this.offset_, 1);
            l_result_view[0] = _value;
        }
        if (bs_endian.is_little) {
            transfor_endian(this.data_, this.offset_, 4);
        }
        this.shift(4);
        return true;
    }
    // 写入64位浮点数
    write_f_64(_value) {
        if (this.left() < 8) {
            return false;
        }
        if(this.offset_ % 8 !== 0) {
            let l_transfor_data = new ArrayBuffer(8);
            let l_result_view = new Float64Array(l_transfor_data, 0, 1);
            l_result_view[0] = _value;
            let l_ui8_view_src = new Uint8Array(l_transfor_data, 0, 8);
            let l_ui8_view_dst = new Uint8Array(this.data_, this.offset_, 8);
            l_ui8_view_dst[0] = l_ui8_view_src[0];
            l_ui8_view_dst[1] = l_ui8_view_src[1];
            l_ui8_view_dst[2] = l_ui8_view_src[2];
            l_ui8_view_dst[3] = l_ui8_view_src[3];
            l_ui8_view_dst[4] = l_ui8_view_src[4];
            l_ui8_view_dst[5] = l_ui8_view_src[5];
            l_ui8_view_dst[6] = l_ui8_view_src[6];
            l_ui8_view_dst[7] = l_ui8_view_src[7];
        } else {
            let l_result_view = new Float64Array(this.data_, this.offset_, 1);
            l_result_view[0] = _value;
        }
        if (bs_endian.is_little) {
            transfor_endian(this.data_, this.offset_, 8);
        }
        this.shift(8);
        return true;
    }

    // 指定长度的uint8_view
    uint8_view(_length) {
        if (this.left() < _length) {
            return null;
        }
        let l_result_view = new Uint8Array(this.data_, this.offset_, _length);
        this.shift(_length);
        return l_result_view;
    }

    left() { return this.length_ - this.offset_; }
    shift(_vl) { this.offset_ = this.offset_ + _vl; }
}

window['namespace'] = window['namespace'] || {};
window['namespace']['bs'] = window['namespace']['bs'] || {};
let bs = window['namespace']['bs'];

bs['bs_endian'] = bs_endian;
bs['bs_in_stream'] = bs_in_stream;
bs['bs_out_stream'] = bs_out_stream;